//==============================================================================
//
//  File        : sensor_S5K5B3GX.c
//  Description : Firmware Sensor Control File
//  Author      : Philip Lin
//  Revision    : 1.0
//
//=============================================================================

#include "includes_fw.h"
#if defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW)||(SENSOR_EN)
#include "config_fw.h"

#if BIND_SENSOR_S5K5B3GX

#include "lib_retina.h"
#include "reg_retina.h"

#include "mmp_reg_vif.h"
#include "mmp_reg_scaler.h"
#include "mmp_reg_gpio.h"
#include "mmp_reg_rawproc.h"

#include "mmpf_sensor.h"
#include "mmpf_hif.h"
#include "mmpf_i2cm.h"
#include "mmpf_vif.h"
#include "isp_if.h"

#include "mmp_reg_i2cm.h"
#include "mmps_3gprecd.h"

#include "hdm_ctl.h"

extern MMP_USHORT  gsSensorPreviewWidth[], gsSensorPreviewHeight[]
extern MMP_USHORT  gsCurPreviewMode, gsCurPhaseCount;
extern MMP_USHORT  gsSensorMode;
extern MMP_USHORT  m_usVideoQuality;
extern MMP_USHORT	m_gsISPCoreID;

extern MMPS_3GPRECD_VIDEO_FORMAT m_VideoFmt;
extern MMP_BOOL    gbAutoFocus;

extern MMP_USHORT m_usResolType;

#if (IQ_TABLE_LOAD_FROM_FLASH == 0)
const ISP_UINT8 Sensor_IQ_CompressedText[] = {
#if(CHIP == P_V2)
#include "isp_842_iq_data_v1_S5K5B3GX.xls.qlz.txt"
#endif
#if (CHIP == VSN_V2)
#endif
};
#endif

//#define SUPPORT_AUTO_FOCUS 0

//#include "sensor_ctl.h"
//#include "preview_ctl.h"
//#include "XDATAmap.h"
//#include "3A_ctl.h"
//#include "S5K5B3GX.h"
//#include "motor_ctl.h"

//------------------------------------------------------------------------------
//  Function    : S5K5B3GX_Sensor_PreviewMode
//  Description :
//------------------------------------------------------------------------------

static void S5K5B3GX_Sensor_PreviewMode(MMP_USHORT usPreviewmode)
{
	gsCurPreviewMode = usPreviewmode;
	//gsCurPhaseCount = usPhasecount;

	switch (usPreviewmode) {
	case 0:
		RTNA_DBG_Str(3, "Sensor 5M (1920x1080) preview mode\r\n");
		//ISP_IF_3A_Control(ISP_3A_DISABLE); //patrick@100518
	    gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_FALSE);

		ISP_IF_IQ_SetColorTransform(0);//julian@091111
		ISP_IF_SNR_SetBeforeCapture();
		ISP_IF_SNR_SetResolution(ISP_SENSOR_RESOL_1920x1080);

		//ISP_IF_3A_Control(ISP_3A_ENABLE); //patrick@100518
	    gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_TRUE);
		break;

	case 1:
		RTNA_DBG_Str(0, "Sensor preview (1920x1080) mode\r\n");
		switch (gsSensorMode) {
		#if defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW)||(VIDEO_R_EN)
		case SENSOR_VIDEO_MODE:
			RTNA_DBG_Str(0, "SENSOR_VIDEO_MODE\r\n");
			ISP_IF_3A_Control(ISP_3A_DISABLE); //patrick@100518
	        gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_FALSE);

//				ISP_IF_IQ_SetColorTransform(1);//julian@091111

			if  (m_VideoFmt == MMPS_3GPRECD_VIDEO_FORMAT_MJPEG) //HB
				ISP_IF_IQ_SetColorTransform(0);//julian@091111
			else
				ISP_IF_IQ_SetColorTransform(1);  // for YUV422/MJPEG mode, tomy@2010_04_30

			ISP_IF_SNR_SetBeforePreview();
			ISP_IF_SNR_SetResolution(ISP_SENSOR_RESOL_1920x1080);

#if 0
			if (m_VideoFmt == MMPS_3GPRECD_VIDEO_FORMAT_H264){
                if(m_usResolType == VIDRECD_RESOL_1920x1080){  // 1080p
                    VR_AE_SetSensorVsync(gIspIfSnrResolInfo.SensorVsync*30/FULLHD_VIDEO_ENCODE_MAX_FRAME_RATE, gIspIfSnrResolInfo.TargetFPS);        
                }
                else{
                    VR_AE_SetSensorVsync(gIspIfSnrResolInfo.SensorVsync, gIspIfSnrResolInfo.TargetFPS);        
                }
            }
#endif  

			ISP_IF_AE_SetFPS(0);
			//ISP_IF_AE_SetFPS(30);

			//ISP_IF_AE_SetFPS(30);
			ISP_IF_3A_Control(ISP_3A_ENABLE);
    	    gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_TRUE);
			break;
		#endif
		}
		break;
	}
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_Initialize
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_Initialize_S5K5B3GX(void)
{
//  MMP_USHORT usData;
	AITPS_GPIO  pGPIO = AITC_BASE_GPIO;
	AITPS_PAD   pPAD  = AITC_BASE_PAD;
	AITPS_VIF  pVIF = AITC_BASE_VIF;

	RTNA_DBG_Str(0, "MMPF_Sensor_Initialize_S5K5B3GX...Begin\r\n");
#if 1

    //Init globol variable used by DSC
    gsSensorPreviewWidth[0] = 1920;
    gsSensorPreviewHeight[0] = 1088;
    // use 1.3M for preview, check sensor preview setting
    gsSensorPreviewWidth[1] = 1920;
    gsSensorPreviewHeight[1] = 1088;

	pPAD->PAD_PSCK = PAD_E8_CURRENT | PAD_E4_CURRENT | PAD_PULL_HIGH;
	pPAD->PAD_PSDA = PAD_E4_CURRENT | PAD_PULL_HIGH;
	pPAD->PAD_PSEN = PAD_E4_CURRENT | PAD_PULL_HIGH;


	#if (CUSTOMER == LGT)  
    GPIO_OutputControl(CAM_EN, TRUE);
	MMPF_OS_Sleep_MS(5);
    #endif

	#if (CUSTOMER == NMG)  
    GPIO_OutputControl(CAM_EN, TRUE);
	MMPF_OS_Sleep_MS(5);
    #endif
	
	MMPF_VIF_SetPIODir(VIF_SIF_SEN, MMP_TRUE);

	#if 1 //PhilipTest@090313
	MMPF_VIF_SetPIOOutput(VIF_SIF_SEN, MMP_TRUE);  //Pin output high
	//RTNA_WAIT_US((15+125)*10); // 15 us + 6 EXT_CLK (48MHz) = 15 us + 125 ns
	#endif
	
	pGPIO->GPIO_EN[3] |= (1 << 16); // config as output mode
	pGPIO->GPIO_DATA[3] |= (1 << 16);  // Turn On Sensor Power
	MMPF_OS_Sleep_MS(10);

	MMPF_VIF_SetPIOOutput(VIF_SIF_SEN, MMP_FALSE);//Pin output low
	
	MMPF_OS_Sleep_MS(5);
  
	pVIF->VIF_SENSR_CLK_CTL  = VIF_SENSR_CLK_EN;
	MMPF_OS_Sleep_MS(5);

#endif

	/*Reset Sensor 500mS*/
	#if (CHIP == P_V2) || (CHIP == VSN_V2)
	MMPF_VIF_SetPIODir(VIF_SIF_RST, MMP_TRUE);

	MMPF_VIF_SetPIOOutput(VIF_SIF_RST, MMP_FALSE);
	MMPF_OS_Sleep_MS(5);

	MMPF_VIF_SetPIOOutput(VIF_SIF_RST, MMP_TRUE);
	MMPF_OS_Sleep_MS(5);
	#endif

	ISP_IF_SNR_Init();

	ISP_IF_MOTOR_Init();

	RTNA_DBG_Str(0, "MMPF_Sensor_Initialize_S5K5B3GX...End\r\n");
	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_PowerDown_S5K5B3GX
//  Description :
//------------------------------------------------------------------------------

static MMP_ERR  MMPF_Sensor_PowerDown_S5K5B3GX(void)
{
	AITPS_VIF  pVIF = AITC_BASE_VIF;
	AITPS_GPIO  pGPIO = AITC_BASE_GPIO;
	AITPS_MIPI pMIPI = AITC_BASE_MIPI;

	pMIPI->MIPI_DATA1_CFG &= ~(MIPI_CSI2_EN);
	pMIPI->MIPI_DATA2_CFG &= ~(MIPI_CSI2_EN);
	MMPF_VIF_EnableInputInterface(MMP_FALSE);

#if SUPPORT_AUTO_FOCUS
	//ISP_IF_AF_SetPos(0);
    //ISP_IF_MOTOR_GoToAFPos();    
	//MMPF_OS_Sleep_MS(10);
#endif

#if (CHIP == P_V2) || (CHIP == VSN_V2)
    //MMPF_VIF_SetPIODir(VIF_SIF_RST, MMP_TRUE);
	//MMPF_VIF_SetPIOOutput(VIF_SIF_RST, MMP_TRUE);  //Pin output high
	//MMPF_OS_Sleep_MS(10);
	//MMPF_VIF_SetPIOOutput(VIF_SIF_RST, MMP_FALSE);//Pin output low
	//MMPF_OS_Sleep_MS(10);
#endif

#if 1
	MMPF_VIF_SetPIODir(VIF_SIF_SEN, MMP_TRUE);
	MMPF_VIF_SetPIOOutput(VIF_SIF_SEN, MMP_TRUE);  //Pin output high
	MMPF_OS_Sleep_MS(5);
#endif

	pVIF->VIF_SENSR_CLK_CTL &= (~ VIF_SENSR_CLK_EN) ;   //output sensor main clock

	#if (CUSTOMER == LGT)  
    GPIO_OutputControl(CAM_EN, FALSE);
	MMPF_OS_Sleep_MS(10);
    #endif

	#if (CUSTOMER == NMG)  
    GPIO_OutputControl(CAM_EN, FALSE);
	MMPF_OS_Sleep_MS(10);
    #endif

#if SUPPORT_AUTO_FOCUS
	#if (CUSTOMER == NMG)  
    GPIO_OutputControl(AF_EN, FALSE);
    #endif

	#if (CUSTOMER == LGT)  
    GPIO_OutputControl(AF_EN, TRUE);
    #endif
#endif

#if 1
	//RTNA_DBG_Str(3, "Config PS_GPIO pin as LOW\r\n");
	pGPIO->GPIO_DATA[3] &= ~(1 << 16);  // Turn Off Sensor Power
#endif
	MMPF_OS_Sleep_MS(5);

	RTNA_DBG_Str3( "MMPF_Sensor_PowerDown_S5K5B3GX() \r\n");
	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetFrameRate_S5K5B3GX
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_SetFrameRate_S5K5B3GX(MMP_UBYTE ubFrameRate)
{
	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetPreviewMode
//  Description :
//------------------------------------------------------------------------------

static MMP_ERR MMPF_Sensor_SetPreviewMode_S5K5B3GX(MMP_USHORT usPreviewmode)
{
	S5K5B3GX_Sensor_PreviewMode(usPreviewmode);

	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetPreviewMode
//  Description :
//------------------------------------------------------------------------------

static MMP_ERR MMPF_Sensor_ChangePreviewMode_S5K5B3GX(
						MMP_USHORT usCurPreviewmode, MMP_USHORT usCurPhasecount,
						MMP_USHORT usNewPreviewmode, MMP_USHORT usNewPhasecount)
{
	S5K5B3GX_Sensor_PreviewMode(usNewPreviewmode);

	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_ChangeMode
//  Description :
//------------------------------------------------------------------------------

/*static*/ MMP_ERR MMPF_Sensor_ChangeMode_S5K5B3GX(MMP_USHORT usPreviewmode, MMP_USHORT usCapturemode)
{
	switch (usPreviewmode) {
	case 0:
		switch (usCapturemode) {
		case 0:
			break;
		case 1:
			break;
		}
		break;
	case 1:
		switch (usCapturemode) {
		case 0:// SXGA preview, 5M capture
			MMPF_Sensor_SetPreviewMode_S5K5B3GX(0);
			// wait 3 frame ...
		   // MMPF_Sensor_WaitFrame(5);
			break;
		case 1:
			MMPF_Sensor_SetPreviewMode_S5K5B3GX(1);
			// wait 3 frame ...
			//MMPF_Sensor_WaitFrame(3);

			break;
		}
		break;
	}

	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_InitializeVIF
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_InitializeVIF_S5K5B3GX(void)
{
	AITPS_MIPI  pMIPI = AITC_BASE_MIPI;
	AITPS_VIF  pVIF = AITC_BASE_VIF;
	AITPS_GPIO  pGPIO = AITC_BASE_GPIO;
	AITPS_PAD   pPAD  = AITC_BASE_PAD;
	//RTNA_DBG_Str(0, "ISP_IF_SNR_Register...S\r\n");

	// register sensor (functions and variables)
	ISP_IF_SNR_Register();
	RTNA_DBG_Str(0, "ISP_IF_SNR_Register...E\r\n");

#if SUPPORT_AUTO_FOCUS
	#if (CUSTOMER == NMG)  
    GPIO_OutputControl(AF_EN, TRUE);
    #endif

	#if (CUSTOMER == LGT)  
    GPIO_OutputControl(AF_EN, FALSE);
    #endif

	MMPF_OS_Sleep_MS(20);
#endif

	// register motor
	ISP_IF_MOTOR_Register();

#if (SENSOR_IF == SENSOR_IF_PARALLEL)	
	MMPF_VIF_RegisterInputInterface(MMPF_VIF_PARALLEL);
	//pVIF->VIF_SENSR_CTL      = VIF_SENSR_LATCH_NEG | VIF_HSYNC_POLAR | VIF_12BPP_OUT_EN;
#else
	pMIPI->MIPI_DATA1_SOT = 0x10; // From KW
	pMIPI->MIPI_DATA2_SOT = 0x10; // From KW
	pMIPI->MIPI_DATA3_SOT = 0x10; // From KW
	pMIPI->MIPI_DATA4_SOT = 0x10; // From KW
	
	MMPF_VIF_RegisterInputInterface(MMPF_VIF_MIPI);
#endif	


	
	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_InitializeISP
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_InitializeISP_S5K5B3GX(void)
{
	volatile MMP_BYTE* pISP = (volatile MMP_BYTE*)AITC_BASE_ISP;

	// check if ISP Lib and IQ are mismatched.
	if (ISP_IF_VER_CheckIQVer() != MMP_ERR_NONE)	
	    return MMP_ERR_NONE;
	//RTNA_DBG_Str(0, "ISP_IF_3A_Register...S\r\n");

	// register 3A
	ISP_IF_3A_Register();
	//RTNA_DBG_Str(0, "ISP_IF_3A_Register...E\r\n");

	//RTNA_DBG_Str(0, "ISP_IF_3A_Init...S\r\n");
	// initialize 3A
	ISP_IF_3A_Init();
	
	// set AF type (ISP_AF_TYPE_ONE_SHOT / ISP_AF_TYPE_CONTINUOUS)
	ISP_IF_AF_SetType(ISP_AF_TYPE_CONTINUOUS);
	//RTNA_DBG_Str(0, "ISP_IF_3A_Init...E\r\n");

	if (m_gsISPCoreID == 868) {
		// ISP pipeline selection (PYTHON_V1 only)
		//APICAL_XBYTE[APICAL_CTL_REG1] &= ~(0x80); // clear auto size
		pISP[0x0B] = 0x30;
		pISP[0x09] = 0x0C;
	}

	return  MMP_ERR_NONE;
}

//============================================================================

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetAFPosition_S5K5B3GX
//  Description :
// ---------------------------------------
static MMP_ERR MMPF_Sensor_SetAFPosition_S5K5B3GX(MMP_UBYTE ubPos)
{
#if 1
	//if (gISPConfig.AutoFocusMode == VENUS_AF_MODE_MANUAL) {
		//gAFConfig.AFPos = ubPos;
		ISP_IF_AF_SetPos(ubPos);
	//}

            //RTNA_DBG_Str(3, "  ubPos = ");       
            //RTNA_DBG_Short(3, ubPos);
            //RTNA_DBG_Str(3, "\r\n");
#endif
	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_Do3AOperation
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_DoAWBOperation_S5K5B3GX(void)
{

	ISP_IF_R_GetAWBAcc();

	ISP_IF_R_DoAWB();
	
	//RTNA_DBG_Str(0, "DoAWBOperation_S5K5B3GX()\r\n");

	return  MMP_ERR_NONE;
}

ISP_UINT32 gISPFrameCnt;

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_DoAEOperation_ST
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_DoAEOperation_ST_S5K5B3GX(void)
{
	static ISP_UINT32 frame_cnt = 0;
	static ISP_UINT32 again, dgain, s_gain;

	//RTNA_DBG_Str(0, "Do3AOperation_S5K5B3GX()\r\n");

	switch (frame_cnt++ % 6) {
//	switch (gISPFrameCnt++ % 6) {
	case 0:
		ISP_IF_AE_Execute();

		again = ISP_IF_AE_GetAGain();
		dgain = ISP_IF_AE_GetDGain();


		break;

	case 1:
		gsSensorFunction->MMPF_Sensor_SetSensorGain(again);
		gsSensorFunction->MMPF_Sensor_SetSensorShutter(ISP_IF_AE_GetShutter(), ISP_IF_AE_GetVsync());
		break;

	case 2:
		//gsSensorFunction->MMPF_Sensor_SetSensorShutter(ISP_IF_AE_GetShutter(), ISP_IF_AE_GetVsync());
		break;
	}

	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_DoAEOperation_END
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_DoAEOperation_END_S5K5B3GX(void)
{
	//ISP_IF_R_DoAE();
	//RTNA_DBG_Str(0, "Do3AOperation_S5K5B3GX()\r\n");

	static ISP_UINT32 frame_cnt = 0;
	static ISP_UINT32 again, dgain, s_gain;
	
	ISP_IF_R_GetAEAcc();

	switch (frame_cnt++ % 6) {
//	switch (gISPFrameCnt++ % 6) {
	case 2:
		again = ISP_IF_AE_GetAGain();
		dgain = ISP_IF_AE_GetDGain();

		ISP_IF_SNR_SetDGain(dgain);
		break;
	}

	return  MMP_ERR_NONE;
}


//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_DoAFOperation
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_DoAFOperation_S5K5B3GX(void)
{
#if SUPPORT_AUTO_FOCUS
	if(gbAutoFocus == MMP_TRUE){
		//VR_AF_GetAcc();
		ISP_IF_R_GetAFAcc();
		ISP_IF_R_DoAF();
	}
#endif

	return  MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_DoIQOperation_S5K5B3GX
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_Sensor_DoIQOperation_S5K5B3GX(void)
{
	// set IQ at frame end to ensure frame sync
	ISP_IF_R_DoIQ();

	//RTNA_DBG_Str(0, "DoIQOperation_S5K5B3GX()\r\n");
	
	return  MMP_ERR_NONE;
}

// Steven ADD
//------------------------------------------------------------------------------
//  Function    : MMPF_SetLightFreq
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR  MMPF_SetLightFreq_S5K5B3GX(MMP_USHORT usMode)
{
	RTNA_DBG_Str(0, "MMPF_SetLightFreq_S5K5B3GX : ");
	RTNA_DBG_Short(0, usMode);
	RTNA_DBG_Str(0, "\r\n");

	/*
	typedef enum {
		VENUS_FLICKER_MODE_OFF              = 0,
		VENUS_FLICKER_MODE_AUTO             = 1,
		VENUS_FLICKER_MODE_60HZ             = 2,
		VENUS_FLICKER_MODE_50HZ             = 3,
		VENUS_FLICKER_MODE_CAL_BASESHUTTER  = 4
	} VENUS_FLICKER_MODE;
	*/

	switch(usMode) {
	case 0:
	case 2:
		//gISPConfig.FlickerMode = VENUS_FLICKER_MODE_60HZ;
		ISP_IF_AE_SetFlicker(ISP_AE_FLICKER_60HZ);
		break;
	case 1:
	case 3:
		//gISPConfig.FlickerMode = VENUS_FLICKER_MODE_50HZ;
		ISP_IF_AE_SetFlicker(ISP_AE_FLICKER_50HZ);
		break;
	default:
		//gISPConfig.FlickerMode = VENUS_FLICKER_MODE_AUTO;
		ISP_IF_AE_SetFlicker(ISP_AE_FLICKER_AUTO);
	}

	return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_SetStableState_S5K5B3GX(MMP_BOOL bStableState)
{
	return  MMP_ERR_NONE;
}

MMP_ERR MMPF_SetHistEQState_S5K5B3GX(MMP_BOOL bHistEQState)
{

	return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetReg_S5K5B3GX(MMP_USHORT usAddr, MMP_USHORT usData)
{
	//MMPF_I2cm_WriteReg(usAddr, usData);
	 MMPF_Sensor_WriteI2C(usAddr,usData);
	return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_GetReg_S5K5B3GX(MMP_USHORT usAddr, MMP_USHORT *usData)
{
	//MMPF_I2cm_ReadReg(usAddr, usData);
	*usData = MMPF_Sensor_ReadI2C(usAddr) ;
	return  MMP_ERR_NONE;
}


static MMP_ERR  MMPF_Sensor_SetImageScene_S5K5B3GX(MMP_USHORT imgSceneID)
{
/*
typedef enum {
	ISP_SCENE_AUTO					= 0,	// scene mode
	ISP_SCENE_PORTRAIT				= 1,	// scene mode
	ISP_SCENE_LANDSCAPE				= 2,	// scene mode
	ISP_SCENE_SPORTS				= 3,	// scene mode
	ISP_SCENE_SUNSET				= 4,	// scene mode
	ISP_SCENE_DUSK					= 5,	// scene mode
	ISP_SCENE_DAWN					= 6,	// scene mode
	ISP_SCENE_NIGHT_SHOT			= 7,	// scene mode
	ISP_SCENE_AGAINST_LIGHT			= 8,	// scene mode
	ISP_SCENE_TEXT					= 9,	// scene mode
	ISP_SCENE_MANUAL				= 10,	// scene mode
	ISP_SCENE_INDOOR				= 11,	// scene mode
	ISP_SCENE_SNOW					= 12,	// scene mode
	ISP_SCENE_FALL					= 13,	// scene mode
	ISP_SCENE_WAVE					= 14,	// scene mode
	ISP_SCENE_FIREWORKS				= 15,	// scene mode
	ISP_SCENE_SHOW_WIN				= 16,	// scene mode
	ISP_SCENE_CANDLE				= 17,	// scene mode
	ISP_SCENE_NONE					= 18	// camera mode
} ISP_SCENE;
*/
	imgSceneID = (imgSceneID % (ISP_SCENE_NONE+1));

	RTNA_DBG_Str(3, "MMPF_SetImageScene_S5K5B3GX : ");
	RTNA_DBG_Byte(3, imgSceneID);
	RTNA_DBG_Str(3, "\r\n");

	//if (g3AConfig.Control3A == ISP_3A_ENABLE)
		MMPF_Sensor_CheckFrameEnd(1);
	ISP_IF_F_SetScene(imgSceneID);

	return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetAEMode_S5K5B3GX(MMP_UBYTE ubAEMode, MMP_UBYTE ubISOMode)
{
/*
typedef enum {
	AE_MODE_AUTO						= 0,
	AE_MODE_MANUAL						= 1,
	AE_MODE_ISO							= 2,
	AE_MODE_SHUTTER						= 3
} VENUS_AE_MODE;
*/
/*
typedef enum {
	AE_ISO_AUTO					= 0,
	AE_ISO_50					= 1,
	AE_ISO_100					= 2,
	AE_ISO_200					= 3,
	AE_ISO_400					= 4,
	AE_ISO_800					= 5,
	AE_ISO_1600					= 6,
	AE_ISO_3200					= 7,
	ISP_AE_ISO_NUM
} VENUS_AE_ISO;
*/
	RTNA_DBG_Str(3, "MMPF_Sensor_SetAEMode_S5K5B3GX : ");
	RTNA_DBG_Byte(3, ubAEMode);
	RTNA_DBG_Str(3, ": ");
	RTNA_DBG_Byte(3, ubISOMode);
	RTNA_DBG_Str(3, "\r\n");

	//if (g3AConfig.Control3A == ISP_3A_ENABLE)
	//MMPF_Sensor_CheckFrameEnd(1);
	//Venus_SetAEMode(ubAEMode, ubISOMode);
	if (ubAEMode == 3)
		ISP_IF_AE_SetISO(ISP_AE_ISO_AUTO);
	else
		ISP_IF_AE_SetISO(ubISOMode);
	
	return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetAFMode_S5K5B3GX(MMP_UBYTE ubAFMode)
{
/*
typedef enum {
	VENUS_AF_MODE_AUTO					= 0,
	VENUS_AF_MODE_MANUAL				= 1,
	VENUS_AF_MODE_MACRO					= 2,
	VENUS_AF_MODE_FULL					= 3,
	VENUS_AF_MODE_MOTOR_TEST            = 4,
	VENUS_AF_MODE_NULL					= 5
} VENUS_AF_MODE;
*/
	RTNA_DBG_Str(3, "MMPF_Sensor_SetAFMode_S5K5B3GX : ");
	RTNA_DBG_Byte(3, ubAFMode);
	RTNA_DBG_Str(3, "\r\n");

	//gISPConfig.AutoFocusMode = (MMP_UBYTE)ubAFMode;
	//if (g3AConfig.Control3A == ISP_3A_ENABLE)
	//	MMPF_Sensor_CheckFrameEnd(1);
	ISP_IF_AF_SetMode(ubAFMode);
	return  MMP_ERR_NONE;
}

//======================================================================//
// function : MMPF_Sensor_SetImageEffect                                //
// parameters:                                                          //
// return :                                                             //
// description :                                                        //
//======================================================================//
static MMP_ERR  MMPF_Sensor_SetImageEffect_S5K5B3GX(MMP_USHORT imgEffectID)
{
/*
typedef enum {
	ISP_IMAGE_EFFECT_NORMAL			= 0,
	ISP_IMAGE_EFFECT_GREY			= 1,
	ISP_IMAGE_EFFECT_SEPIA			= 2,
	ISP_IMAGE_EFFECT_NEGATIVE		= 3,
	ISP_IMAGE_EFFECT_ANTIQUE		= 4,
	ISP_IMAGE_EFFECT_WATERCOLOR		= 5,
	ISP_IMAGE_EFFECT_PORTRAIT		= 6,
	ISP_IMAGE_EFFECT_LANDSCAPE		= 7,
	ISP_IMAGE_EFFECT_SUNSET			= 8,
	ISP_IMAGE_EFFECT_DUSK			= 9,
	ISP_IMAGE_EFFECT_DAWN			= 10,
	ISP_IMAGE_EFFECT_RED			= 11,
	ISP_IMAGE_EFFECT_GREEN			= 12,
	ISP_IMAGE_EFFECT_BLUE			= 13,
	ISP_IMAGE_EFFECT_YELLOW			= 15,
	ISP_IMAGE_EFFECT_EMBOSS			= 17,
	ISP_IMAGE_EFFECT_OIL			= 18,
	ISP_IMAGE_EFFECT_BW				= 19,
	ISP_IMAGE_EFFECT_SKETCH			= 20,
	ISP_IMAGE_EFFECT_CRAYONE		= 21,
	ISP_IMAGE_EFFECT_WHITEBOARD		= 22,
	ISP_IMAGE_EFFECT_BLACKBOARD		= 23,
	ISP_IMAGE_EFFECT_VIVID			= 24,
	ISP_IMAGE_EFFECT_NUM
} ISP_IMAGE_EFFECT;
*/

	imgEffectID = (imgEffectID % (ISP_IMAGE_EFFECT_NUM+1));

	RTNA_DBG_Str(3, "MMPF_Sensor_SetImageEffect_S5K5B3GX : ");
	RTNA_DBG_Byte(3, imgEffectID);
	RTNA_DBG_Str(3, "\r\n");

	//gISPConfig.ImageEffect = (MMP_USHORT)imgEffectID;
	//if (g3AConfig.Control3A == ISP_3A_ENABLE)
	//	MMPF_Sensor_CheckFrameEnd(1);
	ISP_IF_F_SetImageEffect(imgEffectID);

	return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetAWBType_S5K5B3GX(MMP_UBYTE ubType)
{
#if 0
	RTNA_DBG_Str(3, "MMPF_Sensor_SetAWBType_S5K5B3GX : ");
	RTNA_DBG_Byte(3, ubType);
	RTNA_DBG_Str(3, "\r\n");

	cAWBtype = ubType;
#endif
	return  MMP_ERR_NONE;
}
static MMP_ERR  MMPF_Sensor_SetContrast_S5K5B3GX(MMP_SHORT ubLevel)
{
	RTNA_DBG_Str(3, "MMPF_Sensor_Contrast_S5K5B3GX : ");
	RTNA_DBG_Byte(3, ubLevel);
	RTNA_DBG_Str(3, "\r\n");

	//gISPConfig.ContrastLevel = ubLevel;
	ISP_IF_F_SetContrast(ubLevel);

	return  MMP_ERR_NONE;
}
static MMP_ERR  MMPF_Sensor_SetSaturation_S5K5B3GX(MMP_SHORT ubLevel)
{
	RTNA_DBG_Str(3, "MMPF_Sensor_SetSaturation_S5K5B3GX : ");
	RTNA_DBG_Byte(3, ubLevel);
	RTNA_DBG_Str(3, "\r\n");

	//gISPConfig.SaturationLevel = ubLevel;
	ISP_IF_F_SetSaturation(ubLevel);

	return  MMP_ERR_NONE;
}
static MMP_ERR  MMPF_Sensor_SetSharpness_S5K5B3GX(MMP_SHORT ubLevel)
{
	RTNA_DBG_Str(3, "MMPF_Sensor_SetSharpness_S5K5B3GX : ");
	RTNA_DBG_Byte(3, ubLevel);
	RTNA_DBG_Str(3, "\r\n");

	//gISPConfig.SharpnessLevel = ubLevel;
	ISP_IF_F_SetSharpness(ubLevel);

	return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetHue_S5K5B3GX(MMP_SHORT ubLevel)
{
	RTNA_DBG_Str(3, "MMPF_Sensor_SetHue_S5K5B3GX : ");
	RTNA_DBG_Byte(3, ubLevel);
	RTNA_DBG_Str(3, "\r\n");

	ISP_IF_F_SetHue(ubLevel);

	return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetGamma_S5K5B3GX(MMP_SHORT ubLevel)
{
	RTNA_DBG_Str(3, "MMPF_Sensor_SetGamma_S5K5B3GX : ");
	RTNA_DBG_Byte(3, ubLevel);
	RTNA_DBG_Str(3, "\r\n");

	ISP_IF_F_SetGamma(ubLevel);

	return  MMP_ERR_NONE;
}

static MMP_ERR  MMPF_Sensor_SetBacklight_S5K5B3GX(MMP_UBYTE ubLevel)
{
	RTNA_DBG_Str(3, "MMPF_Sensor_SetBacklight_S5K5B3GX : ");
	RTNA_DBG_Byte(3, ubLevel);
	RTNA_DBG_Str(3, "\r\n");

//	ISP_IF_F_SetBacklight(ubLevel);
	if(ubLevel > 1){
		ISP_IF_F_SetWDR(ISP_WDR_DISABLE);
	}
	else{
		ISP_IF_F_SetWDR(ISP_WDR_ENABLE);
	}

	return  MMP_ERR_NONE;
}



static void  MMPF_Sensor_SetCaptureISPSetting_S5K5B3GX(MMP_UBYTE usCaptureBegin)
{
	AITPS_VIF  pVIF = AITC_BASE_VIF;
	MMP_ULONG ulVIF_Width, ulVIF_Height;

	/* ToDo: setting IOS and ISP windows*/
	if(MMP_TRUE == usCaptureBegin){
		ulVIF_Width = (pVIF->VIF_GRAB_PIXL_ED - pVIF->VIF_GRAB_PIXL_ST + 1);
		ulVIF_Height = (pVIF->VIF_GRAB_LINE_ED - pVIF->VIF_GRAB_LINE_ST + 1);
		//gSensorFunc.SetISPWindows(ulVIF_Width,ulVIF_Height);
	}
	
	return;
}

/*Prepare for raw preview zoom*/
static void  MMPF_Sensor_SetISPWindow_S5K5B3GX(MMP_ULONG ulWidth, MMP_ULONG ulHeight)
{
	//gSensorFunc.SetISPWindows(ulWidth,ulHeight);
	return;
}

/*Check AIT can preview in this resolution*/
static MMP_UBYTE  MMPF_Sensor_CheckPreviewAbility_S5K5B3GX(MMP_USHORT usPreviewmode)
{
	switch(usPreviewmode){
		case 0:                 //5M can't preview
			return MMP_TRUE;
			break;
		case 1:                 //1.3M can preview
			return MMP_TRUE;
			break;
	}
	
	return MMP_TRUE;            //5M and 1.3M always can preview
}

static void SetAFWin_S5K5B3GX(MMP_USHORT usIndex, MMP_USHORT usPreviewWidth, MMP_USHORT usPreviewHeight,
					MMP_USHORT  usStartX, MMP_USHORT  usStartY, MMP_USHORT  usWidth, MMP_USHORT  usHeight)
{

	DBG_S3("SetAFWin (TODO)\r\n");
}

//static MMP_BOOL VGAPreview = MMP_TRUE;
static void SetAFEnable_S5K5B3GX(MMP_UBYTE enable)
{
//    if (enable) {
		RTNA_DBG_Str(3, "VENUS_ISP_AUTO_FOCUS_STATUS_START\r\n");
		ISP_IF_AF_Control(ISP_AF_START);
		//actually calling SNR_S5K5B3GX_SetAutoFocusControl()
//    } else {
//        RTNA_DBG_Str(3, "VENUS_ISP_AUTO_FOCUS_STATUS_STOP\r\n");
//        ISP_IF_AF_Control(ISP_AF_STOP);
//    }
}

static MMP_ERR MMPF_Sensor_SetAEEnable_S5K5B3GX(MMP_UBYTE bEnable)
{
	/*
	if (bEnable) {
		g3AConfig.AE_Enabled     = ON;
	}
	else {
		g3AConfig.AE_Enabled     = OFF;
	}*/

	ISP_IF_3A_SetSwitch(ISP_3A_ALGO_AE, bEnable);

	return MMP_ERR_NONE;
}

static MMP_ERR MMPF_Sensor_SetAWBEnable_S5K5B3GX(MMP_UBYTE bEnable)
{
#if 0
	if (bEnable) {
		g3AConfig.AWB_Enabled    = ON;
		g3AConfig.AWBRGB_Enabled = ON;
	}
	else {
		g3AConfig.AWB_Enabled    = OFF;
		g3AConfig.AWBRGB_Enabled = OFF;
	}
#endif


	if(bEnable)
		ISP_IF_AWB_SetMode(ISP_AWB_MODE_AUTO);
	else
		ISP_IF_AWB_SetMode(ISP_AWB_MODE_MANUAL);

	return MMP_ERR_NONE;
}
static void SetAEsmooth_S5K5B3GX(MMP_UBYTE smooth)  {return;}
static MMP_ERR MMPF_Sensor_SetExposureValue_S5K5B3GX(MMP_UBYTE ev)
{
	RTNA_DBG_Str(3, "MMPF_Sensor_SetExposureValue_S5K5B3GX : ");
	//RTNA_DBG_Byte(3, gISPConfig.EV);
	//RTNA_DBG_Str(3, " : ");
	RTNA_DBG_Byte(3, ev);
	RTNA_DBG_Str(3, "\r\n");

	ISP_IF_AE_SetEV(ev);

	return MMP_ERR_NONE;
}

static MMP_UBYTE GetAFPosition_S5K5B3GX     (void){ return 0;/*volatile MMP_UBYTE *GPIO_BASE_B = (volatile MMP_UBYTE *)0x80009400;  return GPIO_BASE_B[0xB0];*/}


static MMP_UBYTE GetAFEnable_S5K5B3GX(void)
{
	//return 0;
	return ISP_IF_AF_GetResult();
}

static MMP_UBYTE GetExposureValue_S5K5B3GX  (void){return ISP_IF_AE_GetEV();}
static MMP_UBYTE GetAEsmooth_S5K5B3GX       (void){return 0;}
//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_Set3AStatus
//  Description :
//------------------------------------------------------------------------------
static MMP_ERR	MMPF_Sensor_Set3AStatus_S5K5B3GX(MMP_BOOL bEnable)
{
	#if 1
	MMPF_Sensor_3A_SetInterrupt(bEnable);
	//#else
	if (bEnable)
		ISP_IF_3A_Control(ISP_3A_ENABLE);
	else
		ISP_IF_3A_Control(ISP_3A_DISABLE);
	#endif
	return	MMP_ERR_NONE;
}

static void  MMPF_Sensor_SetColorID_S5K5B3GX(MMPF_SENSOR_ROTATE_TYPE RotateType)
{
	switch(RotateType) {
	case MMPF_SENSOR_ROTATE_NO_ROTATE:
		break;
	case MMPF_SENSOR_ROTATE_RIGHT_90:
		break;
	case MMPF_SENSOR_ROTATE_RIGHT_180:
		break;
	case MMPF_SENSOR_ROTATE_RIGHT_270:
		break;
	case MMPF_SENSOR_ROTATE_H_MIRROR:
		break;
	case MMPF_SENSOR_ROTATE_V_FLIP:
		break;
	}

	ISP_IF_IQ_SetDirection((ISP_UINT8)RotateType);
	return;
}

MMPF_SENSOR_FUNCTION  SensorFunction_S5K5B3GX =
{
	MMPF_Sensor_Initialize_S5K5B3GX,
	MMPF_Sensor_InitializeVIF_S5K5B3GX,
	MMPF_Sensor_InitializeISP_S5K5B3GX,
	MMPF_Sensor_PowerDown_S5K5B3GX,
	MMPF_Sensor_SetFrameRate_S5K5B3GX,
	MMPF_Sensor_ChangeMode_S5K5B3GX,
	MMPF_Sensor_ChangePreviewMode_S5K5B3GX,
	MMPF_Sensor_SetPreviewMode_S5K5B3GX,
	MMPF_Sensor_SetReg_S5K5B3GX,
	MMPF_Sensor_GetReg_S5K5B3GX,
	MMPF_Sensor_DoAWBOperation_S5K5B3GX,
	MMPF_Sensor_DoAEOperation_ST_S5K5B3GX,
	MMPF_Sensor_DoAEOperation_END_S5K5B3GX,
	MMPF_Sensor_DoAFOperation_S5K5B3GX,
	MMPF_Sensor_DoIQOperation_S5K5B3GX,
	MMPF_Sensor_SetImageEffect_S5K5B3GX,
	MMPF_SetLightFreq_S5K5B3GX,
	MMPF_SetStableState_S5K5B3GX,
	MMPF_SetHistEQState_S5K5B3GX,
	MMPF_Sensor_SetAFPosition_S5K5B3GX,
	SetAFWin_S5K5B3GX,
	SetAFEnable_S5K5B3GX,
	MMPF_Sensor_SetAEEnable_S5K5B3GX,
	MMPF_Sensor_SetAWBEnable_S5K5B3GX,
	MMPF_Sensor_SetExposureValue_S5K5B3GX,
	SetAEsmooth_S5K5B3GX,
	MMPF_Sensor_SetImageScene_S5K5B3GX,
	GetAFPosition_S5K5B3GX,
	GetAFEnable_S5K5B3GX,
	GetExposureValue_S5K5B3GX,
	GetAEsmooth_S5K5B3GX,
	MMPF_Sensor_SetAWBType_S5K5B3GX,
	MMPF_Sensor_SetContrast_S5K5B3GX,
	MMPF_Sensor_SetSaturation_S5K5B3GX,
	MMPF_Sensor_SetSharpness_S5K5B3GX,
	MMPF_Sensor_SetHue_S5K5B3GX,
	MMPF_Sensor_SetGamma_S5K5B3GX,
 //   MMPF_Sensor_SetBacklight_S5K5B3GX,
	MMPF_Sensor_SetAEMode_S5K5B3GX,
	MMPF_Sensor_SetAFMode_S5K5B3GX,
	MMPF_Sensor_SetCaptureISPSetting_S5K5B3GX,
	MMPF_Sensor_SetISPWindow_S5K5B3GX,
	MMPF_Sensor_CheckPreviewAbility_S5K5B3GX,
	MMPF_Sensor_Set3AStatus_S5K5B3GX,
	MMPF_Sensor_SetColorID_S5K5B3GX
};


MMP_USHORT SNR_S5K5B3GX_Reg_Init_Customer[] = {

    //=====================================================================================
    // 1928 x 1088 RAW10
    // $Date: 2010-10-17 15:25:36 +0200 (Sun, 17 Oct 2010) $
    // $Rev: 2273 $
    //=====================================================================================

    0x34DA, 0x0200, // senHal_uMaxGainNormalThr
    0x114A,	0x0025, // smiaRegs_ro_frame_limits_min_frame_blanking_lines

    //=====================================================================================
    // End of APS/Analog setting
    //=====================================================================================
    0x0B06,	0x0180, // smiaRegs_rw_isp_single_defect_correct_enable
    0x0B08,	0x0180, // smiaRegs_rw_isp_dynamic_couplet_correct_enable

    // ISP options
    //WRITE #smiaRegs_rw_edof_edof_mode                00 // EDOF off
    0x0B00, 0x0000, // Shading correction off

    // PLL
    //
    // PLL Parameters
    //
    //              input   25            25             6             6            27            27            9.6           13
    //             system   72            40            72            40            72            40            72            72
    //             output   72            40            72            40            72            40            72            72
    //
    // input_clock_mhz_int  1900 ( 25M)   1900 ( 25M)   0600 (  6M)   0600 (  6M)   1B00 ( 27M)   1B00 ( 27M)   0999 (9.6M)   0D00 ( 13M)
    // vt_pix_clk_div       0005 ( 72M)   0008 ( 40M)   0005 ( 72M)   000C ( 40M)   0005 ( 72M)   000C ( 40M)   0005 ( 72M)   0005 ( 72M)
    // vt_sys_clk_div       0002 (360M)   0002 (320M)   0002 (360M)   0002 (480M)   0002 (360M)   0002 (480M)   0002 (360M)   0002 (360M)
    // pre_pll_clk_div      0005 (  5M)   0005 (  5M)   0001 (  6M)   0001 (  6M)   0006 (4.5M)   0009 (  3M)   0002 (4.8M)   0003 (4.3M)
    // pll_multiplier       0090 (720M)   0080 (640M)   0078 (720M)   00A0 (960M)   00A0 (720M)   0140 (960M)   0096 (720M)   00A6 (720M)
    // op_pix_clk_div       000A ( 72M)   0008 ( 40M)   000A ( 72M)   000C ( 40M)   000A ( 72M)   000C ( 40M)   000A ( 72M)   000A ( 72M)
    // op_sys_clk_div       0001 (720M)   0002 (320M)   0001 (720M)   0002 (480M)   0001 (720M)   0002 (480M)   0001 (720M)   0001 (720M)

    0x3000, 0x1800, // 24MHz

    0x0300, 0x0005, //  72M // vt_pix_clk_div
    0x0302, 0x0002, // 360M // vt_sys_clk_div
    0x0304, 0x0006, //   4M // pre_pll_clk_div
    0x0306, 0x00B4, // 720M // pll_multiplier
    0x0308, 0x000A, //  72M // op_pix_clk_div
    0x030A, 0x0001, // 720M // op_sys_clk_div

    // Frame Size
    //
    // FR for line_length_pck    0830
    // system 40M :                 0242 - 33 fps ; 027C - 30 fps ; 04A8 - 16 fps ; 04F8 - 15 fps
    // system 72M : 023C - 60 fps ; 0410 - 33 fps ; 0479 - 30 fps ; 0862 - 16 fps ; 08F2 - 15 fps

    0x0340, 0x0479, // frame_length_lines // 1145
    0x0342, 0x0830, // line_length_pck  // 2096

    // Input Size & Format
    0x0344, 0x0000, // x_addr_start
    0x0346, 0x0000, // y_addr_start
    0x0348, 0x0787, // 1927 // x_addr_end
    0x034A, 0x043F, // 1087 // y_addr_end

    0x0382, 0x0001, // x_odd_inc
    0x0386, 0x0001, // y_odd_inc

    0x0900, 0x0022, // 0 - Subsampling ; 1 - According to smiaRegs_rw_binning_binning_type
    //0x0901, 0x22, // High nibble - vertical ; Low nibble - horizontal ; 1 - Subsampling / 2 - Binning

    0x0101, 0x0300, // XY Mirror

    // Output Size & Format
    0x034C, 0x0788, // 1928 // x_output_size
    0x034E, 0x0440, // 1088 // y_output_size

    0x0111, 0x000A, // 0 - Parallel ; 2 - MIPI // CSI_signalling_mode
    0x0112, 0x0A0A, // 10 bit output // CCP_data_format
    0x30EE, 0x0000, // PVI mode (no CCP2 framing)
    0x30F4, 0x0008, // RAW10 mode
    0x300C, 0x00, // No embedded lines
    0x30ED, 0x00, // Horizental size is not limited to be multiple of 16

    0x7088, 0x0157, // Increase drive strength on PCLK
    0xB0E6, 0x0000, // outif_mipi_virtual_channel
    
    0x3700, 0x0000, // black level setting

    // Integration Time
    0x0200, 0x0200, // fine_integration_time
    0x0202, 0x0234, // coarse_integration_time

    // Analog Gain
    0x0120, 0x0000, // Global analog gain (not per channel) // analog_gain_mode
    0x0204, 0x0070, // gain=128/(x+16) ; x = 128/gain - 16
    // AGx1 0070
    // AGx2 0030
    // AGx3 001B
    // AGx4 0010
    // AGx5 000A
    // AGx6 0005
    // AGx8 0000

    //0x0206, 0x0070, // analogue_gain_code_greenR
    //0x0208, 0x0070, // analogue_gain_code_red
    //0x020A, 0x0070, // analogue_gain_code_blue
    //0x020C, 0x0070, // analogue_gain_code_greenB

    // Digital Gain
    0x020E, 0x0100, // digital_gain_greenR
    0x0210, 0x0100, // digital_gain_red
    0x0212, 0x0100, // digital_gain_blue
    0x0214, 0x0100, // digital_gain_greenB

    //0x300A, 0x0101, // debug mode - all out

	#if 0
	0x0600, 0x0002, // Output test pattern 
	#endif	

    0x0100, 0x0103,   // Stream on

};
void SNR_S5K5B3GX_InitSensor_Customer(void) {
	// implement your initialize sensor routine here ==============================================
	ISP_UINT16 data ;

	ISP_UINT32 i;

	// initialize I2C ID and type
	/*
	VR_SNR_ConfigI2C(	VR_TableN_GetValueByIndex(&gIspTableHeader.Sensor_Misc, 0),
						VR_TableN_GetValueByIndex(&gIspTableHeader.Sensor_Misc, 1));
	*/

	MMPF_Sensor_ConfigI2C( 0x10, ISP_I2C_TYPE_2A2D);

	// initialize VIF OPRs
#if (SENSOR_IF == SENSOR_IF_PARALLEL)	
	ISP_HDM_IF_InitVIF(ISP_HDM_VIF_IF_PARALLEL, 22);
#elif (SENSOR_IF == SENSOR_IF_MIPI_1_LANE)	
	ISP_HDM_IF_InitVIF(ISP_HDM_VIF_IF_MIPI_SINGLE_0, 22);
#elif (SENSOR_IF == SENSOR_IF_MIPI_2_LANE)		
	ISP_HDM_IF_InitVIF(ISP_HDM_VIF_IF_MIPI_DUAL_01, 22);
#elif (SENSOR_IF == SENSOR_IF_MIPI_4_LANE)		
	ISP_HDM_IF_InitVIF(ISP_HDM_VIF_IF_MIPI_QUAD, 22);
#endif	

	ISP_HDM_IF_EnableSensor(ISP_HDM_SNR_ENABLE_HIGH);

	VR_SNR_WriteI2C(0x6010, 0x0001);
	MMPF_OS_Sleep_MS(10); 

	// set register...........
	for (i = 0; i < sizeof(SNR_S5K5B3GX_Reg_Init_Customer)/4; i++) {
		MMPF_Sensor_WriteI2C(SNR_S5K5B3GX_Reg_Init_Customer[i*2], SNR_S5K5B3GX_Reg_Init_Customer[i*2+1]);

#if 0
		data = MMPF_Sensor_ReadI2C(SNR_S5K5B3GX_Reg_Init_Customer[i*2]) ;
		RTNA_DBG_Str3("Reg :");
		RTNA_DBG_Short3(SNR_S5K5B3GX_Reg_Init_Customer[i*2]);
		RTNA_DBG_Str3(",");
		RTNA_DBG_Short3(data);
		RTNA_DBG_Str3("\r\n");
#endif
	}

    #if (LIMIT_SENSOR_MAX_FRAME_RATE == 30)        
	VR_AE_SetBaseShutter( 343, 286, 343, 286);  // HSYNC = 29.2us
    #else  // 25fps
	VR_AE_SetBaseShutter( 280, 233, 280, 233);
    #endif

	// Set preview resolution as default
	ISP_IF_SNR_SetResolution(ISP_SENSOR_RESOL_1920x1080);
}

void SNR_S5K5B3GX_SetSensorGain_Customer(ISP_UINT32 gain)
{
	ISP_UINT32 sensor_gain = VR_MIN(((128 * ISP_IF_AE_GetAGainBase() + (gain-1)) / VR_MAX(gain, ISP_IF_AE_GetAGainBase())) - 16, 112); //Change Again setting for rounding error

	VR_SNR_WriteI2C(0x0204, sensor_gain);
}

void SNR_S5K5B3GX_SetSensorShutter_Customer(ISP_UINT32 shutter, ISP_UINT32 vsync)
{
	// 1 ~ (frame length line - 3)
	ISP_UINT32 new_vsync = VR_MIN(VR_MAX(shutter + 3, vsync), 0xFFFF);
	ISP_UINT32 new_shutter = VR_MIN(VR_MAX(shutter, 1), new_vsync - 3);

	VR_SNR_WriteI2C(0x0340, new_vsync);
	VR_SNR_WriteI2C(0x0202, new_shutter);
}

void SNR_S5K5B3GX_SetSensorAddMode_Customer(ISP_UINT8 enable)
{
/*	if (ISP_HDM_IF_IsFrameTypePreview()) {
		ISP_UINT8 regval = (enable) ? MMPF_Sensor_ReadI2C(0x3016) | 0x40 : MMPF_Sensor_ReadI2C(0x3016) & ~0x40;

		MMPF_Sensor_WriteI2C(0x0104, 0x01); // grouped_parameter_hold
		MMPF_Sensor_WriteI2C(0x3016, regval);
		MMPF_Sensor_WriteI2C(0x0104, 0x00); // grouped_parameter_hold
	}
*/
}

MMP_USHORT SNR_S5K5B3GX_Reg_1920x1080_Customer[] = {
#if 0

    0x0340, 0x0479, // frame_length_lines // 1145
    0x0342, 0x0830, // line_length_pck  // 2096

    // Input Size & Format
    0x0344, 0x0000, // x_addr_start
    0x0346, 0x0000, // y_addr_start
    0x0348, 0x0787, // 1927 // x_addr_end
    0x034A, 0x043F, // 1087 // y_addr_end

    0x0382, 0x0001, // x_odd_inc
    0x0386, 0x0001, // y_odd_inc

    0x0900, 0x00, // 0 - Subsampling ; 1 - According to smiaRegs_rw_binning_binning_type
    0x0901, 0x22, // High nibble - vertical ; Low nibble - horizontal ; 1 - Subsampling / 2 - Binning

    0x0101, 0x03, // XY Mirror

    // Output Size & Format
    0x034C, 0x0788, // 1928 // x_output_size
    0x034E, 0x0440, // 1088 // y_output_size

#else
    0
#endif

};

void SNR_S5K5B3GX_SetSensorResolution_Customer(ISP_SENSOR_RESOL res)
{
	// implement your change sensor resolution routine here =======================================

	MMP_ULONG i, VIFGrab_H_Start, VIFGrab_H_Length, VIFGrab_V_Start, VIFGrab_V_Length;


	switch (res) {
	case ISP_SENSOR_RESOL_1920x1080:
	case ISP_SENSOR_RESOL_1280x960:
	case ISP_SENSOR_RESOL_1280x720:

		// set register...........
		for (i = 0; i < VR_ARRSIZE(SNR_S5K5B3GX_Reg_1920x1080_Customer)/2; i++) {
			MMPF_Sensor_WriteI2C(SNR_S5K5B3GX_Reg_1920x1080_Customer[i*2], SNR_S5K5B3GX_Reg_1920x1080_Customer[i*2+1]);
		}

		// set target fps and corresponding sensor vsync
		ISP_IF_SNR_SetFPS(0x0479, 30);

		// set vif grab range which is fetched to ISP (for lens shading and 3A window calculation)
		VIFGrab_H_Start     = 1;
		VIFGrab_H_Length    = 1928;
		VIFGrab_V_Start     = 1;
		VIFGrab_V_Length    = 1088;

		// set scaler downsample rate (for scaler calculation)
		ISP_IF_SNR_SetDownSample(1, 1);

		// set color id
		ISP_IF_IQ_SetColorID(3);
		// calcuate shading ratio
		{
			ISP_UINT32 base_x, base_y;
			ISP_UINT32 x_scale_n = 0x200;
			ISP_UINT32 y_scale_n = 0x200;
			ISP_IF_IQ_GetCaliBase(&base_x, &base_y);
			
			x_scale_n = VIFGrab_H_Length * 0x200 / base_x;
			y_scale_n = VIFGrab_V_Length * 0x200 / base_y;
			
			ISP_IF_IQ_SetCaliRatio(	x_scale_n,	//x_scale_n, 
									0x200,		//x_scale_m, 
									0,			//x_offset, 
									y_scale_n,	//y_scale_n, 
									0x200,		//y_scale_m, 
									0);			//y_offset
		}
		break;
	}

	// end of your implementation =================================================================

	// set VIF OPR (Actual sensor output size)
	{
		AITPS_VIF  pVIF = AITC_BASE_VIF;
		volatile MMP_BYTE* pISP = (volatile MMP_BYTE*)AITC_BASE_ISP;

		pVIF->VIF_GRAB_PIXL_ST = VIFGrab_H_Start;
		pVIF->VIF_GRAB_PIXL_ED = VIFGrab_H_Start + VIFGrab_H_Length -1;
		pVIF->VIF_GRAB_LINE_ST = VIFGrab_V_Start ;
		pVIF->VIF_GRAB_LINE_ED = VIFGrab_V_Start + VIFGrab_V_Length -1;
		pVIF->VIF_INT_LINE = VIFGrab_V_Length - 61;// 61;//121;

		if (m_gsISPCoreID == 868) {
			// ISP pipeline selection
			//APICAL_XBYTE[APICAL_CTL_REG1] &= ~(0x80); // clear auto size
			pISP[0x0B] = 0x30;
			pISP[0x09] = 0x0C;

			// IP ColorID setting
			//pISP[0x09] &= ~(0xF0);
			//pISP[0x09] |= (ISP_IF_SNR_GetColorID() == 0 ? 3 : (ISP_IF_SNR_GetColorID() == 1 ? 2 : (ISP_IF_SNR_GetColorID() == 2 ? 1: 0))) * (0x50);
		}
	}
}

void SNR_S5K5B3GX_DoAWB_Customer(void)
{
	static ISP_UINT32 frame_cnt = 0;

	switch (frame_cnt++ % 6) {
//	switch (gISPFrameCnt++ % 6) {
	case 3:
	case 5:
		ISP_IF_AWB_Execute();
		ISP_IF_AWB_SetDGain();
		break;
	}
}

void SNR_S5K5B3GX_DoAF_Customer(void)
{
	static ISP_UINT32 frame_cnt = 0;

	switch (frame_cnt++ % 1) {
//	switch (gISPFrameCnt++ % 1) {
	case 0:
		ISP_IF_AF_Execute();
		break;
	}
}


#if (SENSOR_ID_S5K5B3GX== 0)
MMPF_SENSOR_FUNCTION  *SensorFunction_Module0 = &SensorFunction_S5K5B3GX;
#endif

#if (SENSOR_ID_S5K5B3GX== 1)
MMPF_SENSOR_FUNCTION  *SensorFunction_Module1 = &SensorFunction_S5K5B3GX;
#endif

#endif  //BIND_SENSOR_S5K5B3GX
#endif
